import decimal
import random
from datetime import datetime

from django.db import transaction
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer

from users.models import Address
from .models import Classification, Commodity, CommodityImg, ShoppingCart, Order, OrderGoods
from rest_framework.fields import SerializerMethodField


# 分类序列化器
class ClassificationsSerializer(ModelSerializer):
    class Meta:
        model = Classification
        fields = ['id', 'name']


# 一级分类序列化器
class ParentClassificationsSerializer(ModelSerializer):
    # 一级分类要展示的所有子分类
    classification_set = ClassificationsSerializer(many=True, read_only=True)

    class Meta:
        model = Classification
        fields = ['id', 'name', 'classification_set']


# 商品图片序列化器
class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = "__all__"

        extra_kwargs = {
            "priority": {"read_only": True},
        }


class CommodityImgSerializerSimple(ModelSerializer):
    class Meta:
        model = CommodityImg
        exclude = ["created_time", "updated_time", "is_delete", "commodity", "priority"]

        extra_kwargs = {
            "priority": {"read_only": True},
        }


class CommoditySerializer(ModelSerializer):
    # 一级分类
    classification1_name = serializers.CharField(source='classification1.name', read_only=True)
    classification2_name = serializers.CharField(source='classification2.name', read_only=True)
    # 二级分类
    commodityimg_set = CommodityImgSerializerSimple(many=True, read_only=True)

    class Meta:
        model = Commodity
        exclude = ['is_delete']
        extra_kwargs = {
            'sales': {'read_only': True},
            'comments': {'read_only': True},
        }


"""
cart接口
{
  "id": 2,
  "created_time": "2025-04-21T16:30:34.028491",
  "updated_time": "2025-04-21T16:30:34.028551",
  "number": 1,
  "commodity": 10,
  "user": 8
}
"""


# 购物车序列化器
class ShoppingCartSerializer(ModelSerializer):
    commodityDetail = SerializerMethodField()

    class Meta:
        model = ShoppingCart
        fields = "__all__"

    def get_commodityDetail(self, shoppingcart):
        return CommoditySerializer(shoppingcart.commodity).data

    def validate(self, attrs):
        if attrs['number'] <= 0:
            raise serializers.ValidationError('购物车数量必须大于0')
        elif attrs['number'] > attrs['commodity'].stock:
            raise serializers.ValidationError('库存不足')
        return attrs


# 订单序列化器
class OrderSerializer(ModelSerializer):
    cart = serializers.ListField(write_only=True)

    class Meta:
        model = Order
        fields = "__all__"
        read_only_fields = [
            "order_id",
            "total_count",
            "total_amount",
            "status",
            "user",
        ]

    def create(self, validated_data):
        # 获取用户
        user = self.context['request'].user
        # 生成订单号
        order_id = datetime.now().strftime("%Y%m%d%H%M%S") + '%06d%02d' % (user.id, random.randint(1, 99))
        pay_method = validated_data.get("pay_method")
        try:
            address = Address.objects.get(id=validated_data.get("address"))
        except Address.DoesNotExist:
            raise serializers.ValidationError("地址不存在")
        # 地址模型  省 市 区  详情  谁收  手机号
        address_s = f"""
                {address.province.name}       
        {address.city.name}       
        {address.district.name}       
        {address.place}       
        【{address.receiver}收】       
        {address.mobile}       
        """
        # 创建空白
        # 避免a待支付 b等待 撤销
        # 事务
        with transaction.atomic():
            # 创建一个节点   保存点
            save_point = transaction.savepoint()
            try:
                # 创建空白订单
                order = Order.objects.create(
                    order_id=order_id,  # 订单id
                    total_count=0,  # 商品总数
                    total_amount=decimal.Decimal("0.00"),
                    pay_method=pay_method,
                    status=1 if pay_method == 1 else 2,
                    address=address_s,
                    user=user
                )

                #  得到所有的商品列表 进行循环结算
                # 前端传入的 [2，3，4]
                carts = validated_data.get("cart")

                # 循环的得到每一个购物车内数据id
                for cart_id in carts:
                    while True:
                        # 得到购物车里面的每一个商品的商品数据
                        try:
                            cart = ShoppingCart.objects.get(id=cart_id)
                        except ShoppingCart.DoesNotExist:
                            raise serializers.ValidationError("购物车商品信息不存在")
                        # 得到商品模型对象
                        commodity = cart.commodity
                        # 在结算之前 所有要判断一下 商品的库存 和销量
                        origin_stock = commodity.stock
                        origin_sales = commodity.sales

                        # 核算一下是否超库存
                        if cart.number > origin_stock:
                            raise serializers.ValidationError("库存不足")

                        # 购买  库存减少  销量增加
                        # 新库存  =  原库存 -  购物车购买的商品数量
                        new_stock = origin_stock - cart.number
                        new_sales = origin_sales + cart.number

                        # 商品表修改了
                        # commodity.stock = new_stock
                        # commodity.sales = new_sales
                        # commodity.save()
                        res = Commodity.objects.filter(id=commodity.id, stock=origin_stock).update(stock=new_stock,
                                                                                                   sales=new_sales)
                        if not res:  # 商品被更新了
                            continue
                        # 生成对应订单商品数据
                        OrderGoods.objects.create(
                            number=cart.number,  # 得到单个商品的数量
                            price=commodity.price,  # 得到单个商品的价格
                            order=order,
                            commodity=commodity,
                        )

                        # 订单也要更新
                        # 订单总数
                        order.total_count += cart.number
                        # 订单总价
                        order.total_amount += (cart.number * commodity.price)
                        # 结束while 继续进入for循环
                        break

                # 购物车内所有的商品都循环结算后 订单保存
                order.save()
                # 购物车内的商品要进行清空
                ShoppingCart.objects.filter(id__in=carts).delete()
            except Exception as e:
                # 事务回滚
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError(e)  # 返回爆粗信息
            else:
                # 事务提交
                transaction.savepoint_commit(save_point)

        # 返回创建的订单
        return order

    # 加锁
    # 悲观锁  多个线程  线程 AB 获取同步锁
    #       假设 A 加锁成功，执行操作  b处于等待（阻塞）状态  等a解锁之后 b才能操作

    # 乐观锁  不加锁
    #      线程a和b在进行同步更新的时候，都会判断这个数据是否被修改
    #      如果修改了。就执行定义操作 或者报错